package m2acsis.algebre.impl;

import java.util.ArrayList;
import java.util.List;

import m2acsis.algebre.ElemGroupe;
import m2acsis.algebre.helpers.ToStringHelper;
import m2acsis.algebre.helpers.TypeHelper;

public class Polynome implements ElemGroupe{

	private ElemGroupe[] coefficients;
	protected int degree = 0;
	protected ElemGroupe neutre;
	
	public Polynome(ElemGroupe[] coefficients) {
		
		if(coefficients == null)
			throw new NullPointerException("parametre null");
		
		if(coefficients.length == 0)
			throw new Error("tableau de longueur nulle");
		
		if(!TypeHelper.isNotNull(coefficients))
			throw new NullPointerException("tableau incomplet");
		
		if(!TypeHelper.isSameType(coefficients, coefficients[0].getClass()))
			throw new Error("tableau disparate");
		
		this.coefficients = coefficients;
		degree = coefficients.length;
		neutre = coefficients[0].neutre();
	}
	
	public int getDegree(){
		return degree -1;
	}
	
	@Override
	public ElemGroupe neutre() {
		return new Polynome(new ElemGroupe[]{neutre});
	}

	@Override
	public ElemGroupe oppose() {
		return new Polynome((ElemGroupe[]) getOpposeCoefficients().toArray(new ElemGroupe[]{}));
	}
	
	@SuppressWarnings("unchecked")
	protected <T> List<T> getOpposeCoefficients(){
		
		List<T> coefficientsOppose = new ArrayList<T>(coefficients.length);
		
		for(int i = 0; i < degree; i++){
		
			if(coefficients[i].equals(neutre)){
				coefficientsOppose.add((T) coefficients[i]);
				continue;
			}
			
			coefficientsOppose.add((T) coefficients[i].oppose());
		}
		
		return coefficientsOppose;
	}

	@Override
	public ElemGroupe somme(ElemGroupe e) {
		
		if(e instanceof Polynome){
			Polynome pe = (Polynome)e;
			return new Polynome((ElemGroupe[])getSommeCefficients(pe.coefficients).toArray( new ElemGroupe[]{}));
		}
		
		return null;
	}
	
	protected List<ElemGroupe> getSommeCefficients(ElemGroupe[] e){
		
		
		List<ElemGroupe> result = new ArrayList<ElemGroupe>();
		
		int maxIndeterminee = Math.max(coefficients.length, e.length);
		
		for(int i = 0; i < maxIndeterminee; i++){
			
			ElemGroupe a = null;
			ElemGroupe b = null;
			
			if(i < coefficients.length)
				a = coefficients[i];
			
			if(i < e.length)
				b = e[i];
			
			if(a != null && b != null){
				result.add(a.somme(b));
			}
			else
				if(a != null)
					result.add(a);
				else
					if(b != null)
						result.add(b);
		}
		
		for(int i = result.size(); i > 0 ; i--){
			ElemGroupe elm = result.get(i - 1);
			if(elm.equals(neutre))
				result.remove(i - 1);
			else
				break;
		}
		
		if(result.size() == 0){
			result = new ArrayList<ElemGroupe>();
			result.add(neutre);
			return result;
		}
		
		return result;
	}

	public ElemGroupe[] getCoefficients() {
		return coefficients;
	}
	
	@Override
	public String toString() {
		return ToStringHelper.toString(getCoefficients(), "[", "]");
	}
	
	@Override
	public boolean equals(Object obj) {
		
		if(this == obj){
			return true;
		}
		
		if(obj instanceof Polynome){
			
			Polynome anotherPolynom = (Polynome)obj;
			
			if(degree == anotherPolynom.degree){
				for(int i = 0; i < degree; i++){
					if(!coefficients[i].equals(anotherPolynom.coefficients[i]))
						return false;
				}
				
				return true;
			}
		}
		
		return false;
	}

}
